import {
  AmbientLight,
  AxesHelper,
  BoxGeometry,
  CameraHelper,
  CubeTextureLoader,
  DirectionalLight,
  GridHelper,
  Group,
  Mesh,
  MeshBasicMaterial,
  MeshStandardMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from "three";
import { OrbitControls } from "three/examples/jsm/Addons.js";

export default class Y3DEngine {
  constructor(options) {
    this.options = options || {};
    this.init();
    this.animate();
  }

  init() {
    this.initContainer();
    this.createScene();
    this.createCamera();
    this.createRenderer();
    this.createLight();
    this.createHelper();
    this.createCube();
    this.createCameraControls();
  }

  get width() {
    return this.options.container?.clientWidth || window.innerWidth;
  }
  get height() {
    return this.options.container?.clientHeight || window.innerHeight;
  }

  get aspect() {
    return this.width / this.height;
  }

  initContainer() {
    this.options.container = this.options.container || document.body;
    this.options.container.style = `width: 100vw; height: 100vh;`;
  }

  createScene() {
    this.scene = new Scene();

    const url = "px180.png";
    const cubeTexture = new CubeTextureLoader()
      .setPath("../assets/")
      .load([url, url, url, url, url, url]);
    this.scene.environment = cubeTexture;
  }

  createCamera() {
    this.camera = new PerspectiveCamera(75, this.aspect, 0.1, 1000);
    this.camera.position.set(0, 0, 3);
  }

  createRenderer() {
    this.renderer = new WebGLRenderer({
      antialias: true,
      alpha: true,
    });
    this.renderer.setSize(this.width, this.height);
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setClearColor(0x272727);
    this.options.container.appendChild(this.renderer.domElement);
  }

  createLight() {
    this.lights = new Group();
    this.scene.add(this.lights);
    const ambientLight = new AmbientLight(0xffffff, 0.1);
    this.lights.add(ambientLight);

    const light1 = new DirectionalLight(0xffffff, 0.7);
    light1.position.set(1, 1, 0);
    this.lights.add(light1);

    const light2 = new DirectionalLight(0xffffff, 0.5);
    light2.position.set(-1, 1, 0);
    this.lights.add(light2);

    const light3 = new DirectionalLight(0xffffff, 0.1);
    light3.position.set(0, -1, -1);
    this.lights.add(light3);

    const light4 = new DirectionalLight(0xffffff, 0.1);
    light4.position.set(0, -1, 1);
    this.lights.add(light4);
  }

  createHelper() {
    this.helpers = new Group();
    this.scene.add(this.helpers);

    const gridHelper = new GridHelper(10, 10);
    this.helpers.add(gridHelper);

    const axesHelper = new AxesHelper(1);
    this.helpers.add(axesHelper);
  }

  createCube() {
    this.model = new Group();
    this.scene.add(this.model);

    const geometry = new BoxGeometry(1, 1, 1);
    const material = new MeshStandardMaterial({
      color: 0x666666,
      metalness: 0.1,
      roughness: 0.5,
    });
    const cube = new Mesh(geometry, material);
    this.model.add(cube);
  }

  createCameraControls() {
    this.cameraControls = new OrbitControls(
      this.camera,
      this.renderer.domElement
    );
  }

  animate = () => {
    requestAnimationFrame(this.animate);
    this.renderer.render(this.scene, this.camera);
  };
}

window.addEventListener("DOMContentLoaded", () => {
  const engine = new Y3DEngine({
    container: document.querySelector("#app"),
  });
  window.engine = engine;
});
